package com.css.fxfzdzzh.modules.grid.service;

import com.css.fxfzdzzh.modules.grid.entity.GridEntity;
import com.css.fxfzdzzh.modules.grid.repository.GridRepository;
import com.css.fxfzdzzh.util.PlatformObjectUtils;
import com.css.fxfzdzzh.util.UUIDGenerator;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: fxfzdzzh
 * @Author: lhl
 * @CreateDate: 2023/3/13 14:28
 */
@Service
public class GridService {
    @Resource
    GridRepository gridRepository;

    /**
     * @param nameList  北京市-北京市-海淀区,北京市-北京市-昌平区
     * @param codeList  110101,110102
     * @param kilometer 栅格间隔公里数
     */
    @Transactional(rollbackFor = Exception.class)
    public void getGridByGeom(List<String> nameList, List<String> codeList, String kilometer) {
        gridRepository.delGridEntity();

        List<String> geomList = new ArrayList<>();
        if (nameList != null) {
            for (String name : nameList) {
                String province = null, city = null, county = null, code = null;
                String[] split = name.split("-");
                if (split.length == 1) {
                    province = split[0];
                } else if (split.length == 2) {
                    province = split[0];
                    city = split[1];
                } else if (split.length == 3) {
                    province = split[0];
                    city = split[1];
                    county = split[2];
                }
                geomList.addAll(gridRepository.getGeom(province, city, county, code));
            }
        } else {
            geomList = gridRepository.getGeom(null, null, null, null);
        }
        String geom = geomList.get(0);
        for (int i = 1; i < geomList.size(); i++) {
            geom = gridRepository.getStUnion(geom, geomList.get(i));
        }
        List<List<Double>> listList = getSquareGridCenterLonLatList(geom, kilometer);
        //所有网格线的经度、纬度列表
        List<Double> lonList = listList.get(1);
        List<Double> latList = listList.get(2);
        if (lonList.size() > 0 && latList.size() > 0) {
            for (int i = 0; i < (lonList.size() - 1); i++) {
                double lon = lonList.get(i);
                double lon1 = lonList.get(i + 1);
                // double epiLon = centerLonList.get(i);
                String geomStr = "";
                for (int j = 0; j < (latList.size() - 1); j++) {
                    double lat = latList.get(j);
                    double lat1 = latList.get(j + 1);
                    // double epiLat = centerLatList.get(j);
                    geomStr = geomStr + ",((" + lon + " " + lat + "," + lon1 + " " + lat + "," + lon1 + " " + lat1 +
                            "," + lon + " " + lat1 + "," + lon + " " + lat + "))";
                    // gridGeomStrList.add(geomStr);

                    //String epiGeomStr = "POINT (" + epiLon + " " + epiLat + ")";
                    // centerGeomStrList.add(geomStr);
                }
                geomStr = "MULTIPOLYGON (" + geomStr.substring(1) + ")";
                GridEntity gridEntity = new GridEntity();
                gridEntity.setUuid(UUIDGenerator.getUUID());
                gridEntity.setProvince("");
                gridEntity.setCity("");
                gridEntity.setCounty("");
                gridEntity.setDivisionCode("");
                gridEntity.setKilometer(new BigDecimal(kilometer));
                gridEntity.setGeomText(geomStr);
                // gridEntity.setEpiLocation(epiGeomStr);
                gridRepository.saveGridEntity(gridEntity);
            }
        }

    }

    //获取任务范围的正方形公里格网网格线和震中位置经纬度列表（以右上角为初始点）
    public List<List<Double>> getSquareGridCenterLonLatList(String geom, String kilometer) {
        List<List<Double>> list = new ArrayList<List<Double>>();
        List<Double> extent = getTaskRegionExtent(geom);//获取任务范围最小矩形的经纬度值数组
        if (extent.size() == 4 && !PlatformObjectUtils.isEmpty(kilometer)) {
            double minLongitude = extent.get(0);//经度最小值
            double minLatitude = extent.get(1);//纬度最小值
            double maxLongitude = extent.get(2);//经度最大值
            double maxLatitude = extent.get(3);//纬度最大值
            //以右上角为初始点
            double currentLon = maxLongitude;//经度最大值
            double currentLat = maxLatitude;//纬度最大值
            //距离（米）
            // double meter = Double.parseDouble(kilometer) * 1000;
            double meter = Double.parseDouble(kilometer);
            //将距离转换为度数
            double latIntervalDegree = parseYLengthToDegree(meter);//获取纬度间隔kilometer公里的度数
            //获取纬度为currentLat时，经度间隔kilometer公里的度数
            double lonIntervalDegree = parseXLengthToDegree(currentLat, meter);
            //经度x轴的网格个数
            double lonCount = Math.floor((maxLongitude - minLongitude) / lonIntervalDegree);
            //纬度y轴的网格个数
            double latCount = Math.floor((maxLatitude - minLatitude) / latIntervalDegree);
            //经度x轴的网格余数
            double remLon = (maxLongitude - minLongitude) - lonCount * lonIntervalDegree;
            //纬度y轴的网格余数
            double remLat = (maxLatitude - minLatitude) - latCount * latIntervalDegree;
            //所有网格线的经度、纬度列表
            List<Double> lonList = new ArrayList<Double>();
            List<Double> latList = new ArrayList<Double>();
            for (int i = 0; i <= latCount; i++) {
                currentLat = maxLatitude - latIntervalDegree * i;//当前计算的纬度
                latList.add(currentLat);
            }
            if (remLat > 0) {//纬度y轴的网格余数
                latList.add(minLatitude);//纬度最小值
            }
            for (int j = 0; j <= lonCount; j++) {
                currentLon = maxLongitude - lonIntervalDegree * j;//当前计算的经度
                lonList.add(currentLon);
            }
            if (remLon > 0) {//经度x轴的网格余数
                lonList.add(minLongitude);//经度最小值
            }
            //震中位置经度、纬度列表
            List<Double> centerLonList = new ArrayList<Double>();
            List<Double> centerLatList = new ArrayList<Double>();
            if (lonList.size() >= 2) {
                for (int i = 0; i < lonList.size(); i++) {
                    if (i < lonCount) {
                        double centerLon = lonList.get(i) - lonIntervalDegree / 2;
                        centerLonList.add(centerLon);
                    } else {
                        double centerLon = lonList.get(i) - lonIntervalDegree / 2;
                        if (centerLon >= minLongitude) {
                            centerLonList.add(centerLon);
                        }
                    }
                }
                for (int i = 0; i < latList.size(); i++) {
                    if (i < latCount) {
                        double centerLat = latList.get(i) - latIntervalDegree / 2;
                        centerLatList.add(centerLat);
                    } else {
                        double centerLat = latList.get(i) - latIntervalDegree / 2;
                        if (centerLat >= minLatitude) {
                            centerLatList.add(centerLat);
                        }
                    }
                }
            }
            //返回结果
            list.add(extent);//任务范围最小矩形的经纬度值数组
            list.add(lonList);//所有网格线的经度列表
            list.add(latList);//所有网格线的纬度列表
            list.add(centerLonList);//震中位置经度列表
            list.add(centerLatList);//震中位置纬度列表
        }

        return list;
    }

    //获取任务范围最小矩形的经纬度值数组
    public List<Double> getTaskRegionExtent(String geom) {
        List<Double> list = new ArrayList<Double>();
        if (!PlatformObjectUtils.isEmpty(geom)) {
            //获取区域范围最小矩形
            String extent = gridRepository.getStExtent(geom);
            if (extent.indexOf("BOX(") != -1) {
                extent = extent.split("BOX\\(")[1].split("\\)")[0];
                String[] tempArr = extent.split(",");
                if (tempArr.length == 2) {
                    String[] minTempArr = tempArr[0].split(" ");
                    String[] maxTempArr = tempArr[1].split(" ");
                    if (minTempArr.length == 2 && maxTempArr.length == 2) {
                        double minLongitude = Double.parseDouble(minTempArr[0]);//经度最小值
                        double minLatitude = Double.parseDouble(minTempArr[1]);//纬度最小值
                        double maxLongitude = Double.parseDouble(maxTempArr[0]);//经度最大值
                        double maxLatitude = Double.parseDouble(maxTempArr[1]);//纬度最大值
                        list.add(minLongitude);//经度最小值
                        list.add(minLatitude);//纬度最小值
                        list.add(maxLongitude);//经度最大值
                        list.add(maxLatitude);//纬度最大值
                    }
                }
            }
        }

        return list;
    }

    /**
     * 定义地球半径（米）
     */
    //private final double R_EARTH = 6371000;
    private final double R_EARTH = 6378137;

    /**
     * 定义地球赤道周长（米）
     */
    private final double P_EARTH = 2 * Math.PI * R_EARTH;

    /**
     * 将Y轴的长度（米）转换成纬度
     *
     * @param length
     * @return
     */
    public double parseYLengthToDegree(double length) {
        //将length长度转换为度数
        double yDegree = length / P_EARTH * 360;
        return yDegree;
    }

    /**
     * 根据所在纬度，将X轴的长度（米）转换成经度
     * （因为不同纬度下，1°经度代表的长度不同）
     *
     * @param y      所在纬度
     * @param length 线段长度
     * @return
     */
    public double parseXLengthToDegree(double y, double length) {
        //将角度（纬度）转换为弧度
        double latRadian = Math.toRadians(y);
        //计算当前纬度地球周长
        double latPEarth = P_EARTH * Math.cos(latRadian);
        //将length长度转换为度数
        double xDegree = length / latPEarth * 360;
        return xDegree;
    }

}
